package com.hnichr.ping.sms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hnichr.ping.common.DictEnum;
import com.hnichr.ping.common.vo.MobileResultVo;
import com.hnichr.ping.common.vo.SendResultVo;
import com.hnichr.ping.common.vo.SmsSendVo;
import com.hnichr.ping.signature.SignatureProvider;
import com.hnichr.ping.sms.service.SmsSendService;
import com.hnichr.ping.signature.SignatureHolder;
import com.hnichr.ping.tenant.entity.Tenant;
import com.hnichr.ping.sms.channel.SmsChannelProvider;
import com.hnichr.ping.sms.entity.SmsChannel;
import com.hnichr.ping.sms.entity.SmsSend;
import com.hnichr.ping.sms.mapper.SmsChannelMapper;
import com.hnichr.ping.sms.mapper.SmsSendMapper;
import com.hnichr.ping.tenant.entity.TenantBizType;
import com.hnichr.ping.tenant.mapper.TenantBizTypeMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SmsSendServiceImpl implements SmsSendService {

    //发送误差时间10分钟
    private static Long SEND_INTERTAL = 10*60*1000L;

    @Value("${sms.batchMaxSize}")
    private int batchMaxSize=500;
    @Autowired
    private List<SmsChannelProvider> channelProviderList;

    @Autowired
    private SmsChannelMapper smsChannelMapper;

    @Autowired
    private SmsSendMapper smsSendMapper;

    @Autowired
    private TenantBizTypeMapper tenantBizTypeMapper;

    @Autowired
    private SignatureHolder signatureHolder;

    @Override
    public SendResultVo paramVerify(SmsSendVo smsSendVo, String appSecret){
        TreeMap<String,String> treeMap = new TreeMap<>();
        //判空
        List<String> invalidParamList = new ArrayList<>();
        if(StringUtils.isBlank(smsSendVo.getAppKey())) {
            invalidParamList.add("appKey");
        }
        else{
            treeMap.put("appKey",smsSendVo.getAppKey());
        }

        if(StringUtils.isBlank(smsSendVo.getMobiles())){
            invalidParamList.add("mobiles");
        }
        else{
            treeMap.put("mobiles",smsSendVo.getMobiles());
        }

        /*if(StringUtils.isBlank(smsSendVo.getSmsContent())){
            invalidParamList.add("smsContent");
        }
        else{
            treeMap.put("smsContent",smsSendVo.getSmsContent());
        }*/

        if(StringUtils.isBlank(smsSendVo.getTimestamp())){
            invalidParamList.add("timestamp");
        }
        else{
            treeMap.put("timestamp",smsSendVo.getTimestamp());
        }

        if(StringUtils.isBlank(smsSendVo.getNonce())){
            invalidParamList.add("nonce");
        }
        else{
            treeMap.put("nonce",smsSendVo.getNonce());
        }

        if(StringUtils.isBlank(smsSendVo.getSignatureMethod())){
            invalidParamList.add("signatureMethod");
        }
        else{
            treeMap.put("signatureMethod",smsSendVo.getSignatureMethod());
        }

        if(StringUtils.isBlank(smsSendVo.getSignature())){
            invalidParamList.add("signature");
        }
        if(CollectionUtils.isNotEmpty(invalidParamList)){
            String msg = String.join(",",invalidParamList);
            return SendResultVo.failed("["+msg+"]不能为空");
        }

        if(smsSendVo.getMobiles().split(",").length>batchMaxSize){
            return SendResultVo.failed("手机号码最大不能超过["+batchMaxSize+"]个");
        }

        SignatureProvider provider = signatureHolder.getProvider(smsSendVo.getSignatureMethod());
        if(provider==null){
            return SendResultVo.failed("signatureMethod不被支持");
        }

        String localSign = provider.getSignature(treeMap,appSecret);
        if(!StringUtils.equals(localSign,smsSendVo.getSignature())){
            return SendResultVo.failed("signature验证失败");
        }

        long remoteTime = Long.parseLong(smsSendVo.getTimestamp());
        long serverTime = new Date().getTime();

        if(Math.abs(remoteTime-serverTime)>SEND_INTERTAL){
            return SendResultVo.failed("timestamp与服务器时间差异超限");
        }
        return SendResultVo.success();
    }


    @Override
    public SmsChannel getSmsChannel(String channelCode){
        LambdaQueryWrapper<SmsChannel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SmsChannel::getChannelCode,channelCode);
        return smsChannelMapper.selectOne(queryWrapper);
    }


    @Override
    public SendResultVo smsSend(SmsSendVo smsSendVo, Tenant tenant, SmsChannel channel, TenantBizType tenantBizType) {


        Set<String> mobileSet = new HashSet<>(Arrays.asList(smsSendVo.getMobiles().split(",")));

        Map<String,SmsSend> sendMap = new HashMap<>();
        for(String mobile: mobileSet){
            SmsSend smsSend = new SmsSend();
            smsSend.setChannelCode(channel.getChannelCode());
            smsSend.setTenantCode(tenant.getTenantCode());
            smsSend.setCreateTime(new Date());
            smsSend.setTarget(mobile);
            smsSend.setContent(smsSendVo.getSmsContent());
            smsSendMapper.insert(smsSend);
            sendMap.put(mobile,smsSend);
        }

        //如果有条数限制，先扣减短信条数
        if("0".equals(tenantBizType.getUnlimited())){
            int effectNum = tenantBizTypeMapper.reduceSmsQuantity(mobileSet.size(),tenantBizType.getId());
            if(effectNum<1){
                for(Map.Entry<String,SmsSend> sendEntity:sendMap.entrySet()){
                    SmsSend smsSend = sendEntity.getValue();
                    smsSend.setSendTime(new Date());
                    smsSend.setResult(DictEnum.SEND_RESULT.FAILED.getCode());
                    smsSend.setMsg("短信余量不足");
                    smsSendMapper.updateById(smsSend);
                }
                return SendResultVo.failed("短信余量不足!");
            }
        }

        SendResultVo resultVo=null;
        for(SmsChannelProvider provider:channelProviderList){
            if(provider.accept(channel.getProviderCode())){
                SendResultVo paramValidResult = provider.paramVerify(smsSendVo);
                if(!paramValidResult.isSuccess()){
                    return paramValidResult;
                }
                resultVo = provider.send(channel,smsSendVo);
                break;
            }
        }

        if(resultVo==null){
            for(Map.Entry<String,SmsSend> sendEntity:sendMap.entrySet()){
                SmsSend smsSend = sendEntity.getValue();
                smsSend.setSendTime(new Date());
                smsSend.setResult(DictEnum.SEND_RESULT.FAILED.getCode());
                smsSend.setMsg("发送失败");
                smsSendMapper.updateById(smsSend);
            }
            resultVo = SendResultVo.failed("未找到渠道["+channel.getChannelCode()+"]的provider!");
        }
        else if(!resultVo.isSuccess()){
            for(Map.Entry<String,SmsSend> sendEntity:sendMap.entrySet()){
                SmsSend smsSend = sendEntity.getValue();
                smsSend.setSendTime(new Date());
                smsSend.setResult(DictEnum.SEND_RESULT.FAILED.getCode());
                smsSend.setMsg(resultVo.getMsg());
                smsSendMapper.updateById(smsSend);
            }
        }
        else{
            for(MobileResultVo mobileResultVo:resultVo.getResult()){
                SmsSend smsSend = sendMap.get(mobileResultVo.getMobile());
                if(smsSend==null){
                    continue;
                }
                smsSend.setSendTime(new Date());
                smsSend.setResult(mobileResultVo.getResultCode());
                smsSend.setMsg(mobileResultVo.getMsg());
                smsSendMapper.updateById(smsSend);
            }
        }
        if(!resultVo.isSuccess()){
            tenantBizTypeMapper.recoverSmsQuantity(mobileSet.size(),tenantBizType.getId());
        }

        return resultVo;
    }
}
